package org.ovgu.coursify.data;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.ovgu.coursify.HomeActivity;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class DataBase {
	private static final String CONTENT_ATTRIBUTE = "content";
	private static final String COMMENT_TAG = "comment";
	public static final String COMMENTS_XML_FILLE = "comments.xml";
	private static List<Profile> profiles;
	private static List<Comment> comments;
	private static Map<Integer, Lecture> lectures;

	private static void loadProfiles() {
		profiles = new Vector<Profile>();

		profiles.add(new Profile("aaaa", "bbbb", "student", "Student name",
				new int[] { 10, 11 }));
		profiles.add(new Profile("student1", "student1", "student",
				"Student name", new int[] { 10, 11 }));
		profiles.add(new Profile("student2", "student2", "student",
				"Student name 2", new int[] { 10, 12 }));
		profiles.add(new Profile("professor1", "professor1", "docent",
				"Docent A", null));
		profiles.add(new Profile("professor2", "professor2", "docent",
				"Docent B", null));
	}

	private static void loadComments() {
		comments = new Vector<Comment>();

		Document document = loadXML(COMMENTS_XML_FILLE);
		if (document != null) {
			Node root = document.getFirstChild();
			NodeList elements = root.getChildNodes();
			for (int i = 0; i < elements.getLength(); i++) {
				Node element = elements.item(i);
				if (element.getNodeName().equals(COMMENT_TAG)) {
					NamedNodeMap attributes = element.getAttributes();
					int lecture = Integer.parseInt(attributes.getNamedItem(
							"lecture").getTextContent());
					String comment = attributes.getNamedItem(CONTENT_ATTRIBUTE)
							.getTextContent();
					float rating = Float.parseFloat(attributes.getNamedItem(
							"rating").getTextContent());
					long date = Long.parseLong(attributes.getNamedItem("time")
							.getTextContent());
					comments.add(new Comment(lecture, comment, rating, date));
				}
			}
		}
	}

	public static void saveComments() {
		Document document = generateCommentsDocument();
		try {
			Transformer transformer = TransformerFactory.newInstance()
					.newTransformer();
			Result output = new StreamResult(new File(HomeActivity.getContext()
					.getFilesDir(), COMMENTS_XML_FILLE));
			Source input = new DOMSource(document);
			transformer.transform(input, output);
		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
		} catch (TransformerFactoryConfigurationError e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			e.printStackTrace();
		}
	}

	private static Document generateCommentsDocument() {
		Document document = docBuilder.newDocument();
		Element root = document.createElement("comments");
		for (Comment comment : comments) {
			Element commentElement = document.createElement(COMMENT_TAG);
			commentElement.setAttribute("lecture",
					Integer.toString(comment.getLecture()));
			commentElement
					.setAttribute(CONTENT_ATTRIBUTE, comment.getContent());
			commentElement.setAttribute("rating",
					Float.toString(comment.getRating()));
			commentElement.setAttribute("time",
					Long.toString(comment.getDateTime().getTime()));
			root.appendChild(commentElement);
		}
		document.appendChild(root);
		return document;
	}

	private static void loadLectures() {
		lectures = new TreeMap<Integer, Lecture>();
		lectures.put(10, new Lecture("Software engineering(Lect)",
				"Prof. Dr. Frank Ortmeier", 10));
		lectures.put(11, new Lecture("Softwere engineering(Exer)",
				"Mike Mikuteit", 11));
		lectures.put(12, new Lecture("Softwere engineering(Exer)",
				"Michael Lipaczewski", 12));
		lectures.put(20, new Lecture("Grundlagen C++(Lect)", "Acagamics team",
				20));
		lectures.put(21, new Lecture("Grundlagen C++(Exer)", "Acagamics team",
				21));
	}

	private static DocumentBuilder docBuilder;

	public static Document loadXML(String file) {
		if (docBuilder == null) {
			DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
					.newInstance();
			try {
				docBuilder = docBuilderFactory.newDocumentBuilder();
			} catch (ParserConfigurationException e) {
				e.printStackTrace();
			}
		}

		if (docBuilder != null) {
			try {
				Document doc = docBuilder.parse(new File(HomeActivity
						.getContext().getFilesDir(), file));
				return doc;
			} catch (SAXException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	public static Lecture getLection(int i) {
		if (lectures == null)
			loadLectures();
		return lectures.get(i);
	}

	public static List<Lecture> getLectures(Profile profile) {
		if (lectures == null)
			loadLectures();
		Vector<Lecture> result = new Vector<Lecture>();
		if (profile.getLectures() != null) {
			for (Integer i : profile.getLectures()) {
				result.add(lectures.get(i));
			}
		}
		return result;
	}

	public static List<Lecture> getLectures() {
		if (lectures == null)
			loadLectures();
		return makeList(lectures.values());
	}

	public static <E> List<E> makeList(Iterable<E> iter) {
		List<E> list = new ArrayList<E>();
		for (E item : iter) {
			list.add(item);
		}
		return list;
	}

	public static List<Comment> getComments(int lecutre) {
		if (comments == null)
			loadComments();
		List<Comment> results = new ArrayList<Comment>();
		for (Comment comment : comments) {
			if (comment.getLecture() == lecutre) {
				results.add(comment);
			}
		}
		return results;
	}

	public static List<Profile> getProfiles() {
		if (profiles == null)
			loadProfiles();
		return profiles;
	}

	public static void addComment(int lecture, String content, float rating) {
		if (comments == null)
			loadComments();
		comments.add(new Comment(lecture, content, rating));
	}
}
